package com.woohua.thread.wait;

import java.util.Vector;

/***
 * @title TaskQueue
 * @description: 任务队列列表
 *      1、notify 唤醒队列中的一个等待对象
 *          1-1 判断使用notify的依据有：
 *              1）所有等待的线程拥有相同的等待条件
 *              2）所有等待线程被唤醒后，执行相同的操作
 *              3）只需要唤醒一个线程
 *      2、notifyAll 唤醒队列中的所有等待对象
 *          防止线程被饿死
 *      3、wait 和 sleep
 *         1) wait 会释放锁而sleep不会
 *         2） wait 只能再synchronized 代码块中执行, 而 sleep 没有限制
 *         3） wait 的使用更像事件监听机制，工作线程听某个事件（如任务队列），事件到达后通知工作线程，
 *            而sleep的使用更像轮询机制，不断的轮询任务队列中是否有任务。在处理任务队列这个场景上使用wait更优一些。
 *
 *       总结：
 *       1、wait和notify、notifyAll 只能出现在synchronized 代码块中
 *       2、obj.wait()方法基于obj对象生成了一个wait队列
 *       3、调用obj.wait()的同步代码块的线程进入了等待队列，而不是obj进入等待队列
 *       4、使用notify和notifyAll 要根据实际场景具体分析
 *       5、任务队列场景wait优先于sleep, 可避免不必要的轮询
 * @author woo hua
 * @version 1.0.0
 * @create 2023/3/9 13:46
 **/
public class TaskQueue {

    private Vector<String> taskVector = new Vector<>();

    /**
     * 添加任务
     *
     * @param task
     */
    public synchronized void addTask(String task) {
        System.out.println(task + " has generated.");
        taskVector.add(task);
        // 唤醒
        this.notify();
    }

    public synchronized String removeTask() {
        if (!taskVector.isEmpty()) {
            return taskVector.remove(0);
        } else {
            try {
                System.out.println(Thread.currentThread().getName() + " waiting...");
                // 没有任务则进入等待队列
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}
